<?php
/**
 * 系统配置管理服务
 * 提供完整的系统参数配置功能，支持分组管理、类型验证、缓存机制等
 */

namespace app\service;

use think\facade\Db;
use think\facade\Cache;

class SystemConfigService
{
    /**
     * 配置分组定义
     */
    private const CONFIG_GROUPS = [
        'basic' => '基础设置',
        'security' => '安全设置',
        'workflow' => '工作流设置',
        'notification' => '通知设置',
        'system' => '系统设置',
        'integration' => '集成设置',
        'appearance' => '外观设置',
        'performance' => '性能设置'
    ];

    /**
     * 配置类型定义
     */
    private const CONFIG_TYPES = [
        'text' => '文本',
        'number' => '数字',
        'bool' => '布尔值',
        'json' => 'JSON',
        'select' => '选择框',
        'multiselect' => '多选框',
        'textarea' => '长文本',
        'password' => '密码',
        'url' => '网址',
        'email' => '邮箱',
        'file' => '文件',
        'image' => '图片'
    ];

    /**
     * 默认系统配置
     */
    private const DEFAULT_CONFIGS = [
        // 基础设置
        'basic' => [
            'site_name' => ['value' => '勾股OA系统', 'type' => 'text', 'desc' => '网站名称'],
            'site_title' => ['value' => '企业办公自动化系统', 'type' => 'text', 'desc' => '网站标题'],
            'site_keywords' => ['value' => 'OA,办公,管理,勾股', 'type' => 'text', 'desc' => '网站关键词'],
            'site_description' => ['value' => '勾股OA企业办公自动化系统', 'type' => 'textarea', 'desc' => '网站描述'],
            'company_name' => ['value' => '某某科技有限公司', 'type' => 'text', 'desc' => '公司名称'],
            'company_address' => ['value' => '', 'type' => 'text', 'desc' => '公司地址'],
            'company_phone' => ['value' => '', 'type' => 'text', 'desc' => '公司电话'],
            'company_email' => ['value' => '', 'type' => 'email', 'desc' => '公司邮箱'],
            'timezone' => ['value' => 'Asia/Shanghai', 'type' => 'select', 'desc' => '时区设置'],
            'date_format' => ['value' => 'Y-m-d', 'type' => 'select', 'desc' => '日期格式']
        ],

        // 安全设置
        'security' => [
            'login_attempts' => ['value' => 5, 'type' => 'number', 'desc' => '登录尝试次数限制'],
            'login_lock_time' => ['value' => 300, 'type' => 'number', 'desc' => '登录锁定时间（秒）'],
            'session_timeout' => ['value' => 7200, 'type' => 'number', 'desc' => '会话超时时间（秒）'],
            'password_min_length' => ['value' => 6, 'type' => 'number', 'desc' => '密码最小长度'],
            'password_complexity' => ['value' => false, 'type' => 'bool', 'desc' => '强制密码复杂度'],
            'enable_two_factor' => ['value' => false, 'type' => 'bool', 'desc' => '启用双因子认证'],
            'api_rate_limit' => ['value' => 100, 'type' => 'number', 'desc' => 'API访问频率限制'],
            'upload_max_size' => ['value' => 10, 'type' => 'number', 'desc' => '文件上传大小限制（MB）'],
            'allowed_file_types' => ['value' => 'jpg,jpeg,png,gif,pdf,doc,docx,xls,xlsx', 'type' => 'text', 'desc' => '允许上传的文件类型']
        ],

        // 工作流设置
        'workflow' => [
            'auto_approval_timeout' => ['value' => 24, 'type' => 'number', 'desc' => '自动审批超时时间（小时）'],
            'enable_email_notification' => ['value' => true, 'type' => 'bool', 'desc' => '启用邮件通知'],
            'enable_sms_notification' => ['value' => false, 'type' => 'bool', 'desc' => '启用短信通知'],
            'approval_reminder_time' => ['value' => 2, 'type' => 'number', 'desc' => '审批提醒时间（小时）'],
            'max_approval_steps' => ['value' => 10, 'type' => 'number', 'desc' => '最大审批步骤数'],
            'enable_approval_delegation' => ['value' => true, 'type' => 'bool', 'desc' => '启用审批委托'],
            'enable_cc_notification' => ['value' => true, 'type' => 'bool', 'desc' => '启用抄送通知']
        ],

        // 通知设置
        'notification' => [
            'smtp_host' => ['value' => '', 'type' => 'text', 'desc' => 'SMTP服务器'],
            'smtp_port' => ['value' => 587, 'type' => 'number', 'desc' => 'SMTP端口'],
            'smtp_username' => ['value' => '', 'type' => 'text', 'desc' => 'SMTP用户名'],
            'smtp_password' => ['value' => '', 'type' => 'password', 'desc' => 'SMTP密码'],
            'smtp_encryption' => ['value' => 'tls', 'type' => 'select', 'desc' => 'SMTP加密方式'],
            'mail_from_name' => ['value' => '勾股OA系统', 'type' => 'text', 'desc' => '发件人名称'],
            'mail_from_address' => ['value' => '', 'type' => 'email', 'desc' => '发件人邮箱'],
            'sms_provider' => ['value' => 'aliyun', 'type' => 'select', 'desc' => '短信服务商'],
            'sms_app_key' => ['value' => '', 'type' => 'text', 'desc' => '短信AppKey'],
            'sms_app_secret' => ['value' => '', 'type' => 'password', 'desc' => '短信AppSecret']
        ],

        // 系统设置
        'system' => [
            'debug_mode' => ['value' => false, 'type' => 'bool', 'desc' => '调试模式'],
            'log_level' => ['value' => 'error', 'type' => 'select', 'desc' => '日志级别'],
            'cache_driver' => ['value' => 'file', 'type' => 'select', 'desc' => '缓存驱动'],
            'backup_auto' => ['value' => true, 'type' => 'bool', 'desc' => '自动备份'],
            'backup_interval' => ['value' => 7, 'type' => 'number', 'desc' => '备份间隔（天）'],
            'maintenance_mode' => ['value' => false, 'type' => 'bool', 'desc' => '维护模式'],
            'data_retention_days' => ['value' => 365, 'type' => 'number', 'desc' => '数据保留天数']
        ]
    ];

    /**
     * 获取所有配置
     * @param string $group 配置分组
     * @return array
     */
    public function getAllConfigs(string $group = ''): array
    {
        // 检查缓存
        $cacheKey = 'system_configs' . ($group ? '_' . $group : '');
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }

        try {
            $query = Db::name('system_config');
            if ($group) {
                $query->where('group', $group);
            }
            
            $configs = $query->order('sort asc, id asc')->select()->toArray();
            
            $result = [];
            foreach ($configs as $config) {
                if (!isset($result[$config['group']])) {
                    $result[$config['group']] = [
                        'name' => self::CONFIG_GROUPS[$config['group']] ?? $config['group'],
                        'configs' => []
                    ];
                }
                
                $result[$config['group']]['configs'][$config['key']] = [
                    'key' => $config['key'],
                    'value' => $this->parseValue($config['value'], $config['type']),
                    'raw_value' => $config['value'],
                    'type' => $config['type'],
                    'desc' => $config['desc'],
                    'options' => $config['options'] ? json_decode($config['options'], true) : null,
                    'sort' => $config['sort'],
                    'status' => $config['status']
                ];
            }
            
            // 缓存配置（30分钟）
            Cache::set($cacheKey, $result, 1800);
            
            return $result;
            
        } catch (\Exception $e) {
            return $this->getDefaultConfigsByGroup($group);
        }
    }

    /**
     * 获取单个配置值
     * @param string $key 配置键
     * @param mixed $default 默认值
     * @return mixed
     */
    public function get(string $key, $default = null)
    {
        // 先从缓存获取
        $cacheKey = 'config_' . $key;
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }

        try {
            $config = Db::name('system_config')
                ->where('key', $key)
                ->where('status', 1)
                ->find();
            
            if ($config) {
                $value = $this->parseValue($config['value'], $config['type']);
                Cache::set($cacheKey, $value, 1800);
                return $value;
            }
            
            return $default;
            
        } catch (\Exception $e) {
            return $default;
        }
    }

    /**
     * 设置配置值
     * @param string $key 配置键
     * @param mixed $value 配置值
     * @param string $desc 配置描述
     * @param string $type 配置类型
     * @param string $group 配置分组
     * @param array $options 选项配置
     * @return bool
     */
    public function set(string $key, $value, string $desc = '', string $type = 'text', string $group = 'basic', array $options = []): bool
    {
        try {
            $data = [
                'key' => $key,
                'value' => $this->formatValue($value, $type),
                'desc' => $desc,
                'type' => $type,
                'group' => $group,
                'options' => $options ? json_encode($options, JSON_UNESCAPED_UNICODE) : '',
                'update_time' => time()
            ];

            $existing = Db::name('system_config')->where('key', $key)->find();
            
            if ($existing) {
                $result = Db::name('system_config')
                    ->where('key', $key)
                    ->update($data);
            } else {
                $data['create_time'] = time();
                $data['sort'] = 0;
                $data['status'] = 1;
                $result = Db::name('system_config')->insert($data);
            }

            if ($result) {
                // 清除缓存
                $this->clearConfigCache($key, $group);
                return true;
            }
            
            return false;
            
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 批量设置配置
     * @param array $configs 配置数组
     * @return bool
     */
    public function setBatch(array $configs): bool
    {
        try {
            Db::startTrans();
            
            foreach ($configs as $key => $data) {
                $value = $data['value'] ?? $data;
                $desc = $data['desc'] ?? '';
                $type = $data['type'] ?? 'text';
                $group = $data['group'] ?? 'basic';
                $options = $data['options'] ?? [];
                
                if (!$this->set($key, $value, $desc, $type, $group, $options)) {
                    throw new \Exception("设置配置 {$key} 失败");
                }
            }
            
            Db::commit();
            
            // 清除所有配置缓存
            $this->clearAllConfigCache();
            
            return true;
            
        } catch (\Exception $e) {
            Db::rollback();
            return false;
        }
    }

    /**
     * 删除配置
     * @param string $key 配置键
     * @return bool
     */
    public function delete(string $key): bool
    {
        try {
            $config = Db::name('system_config')->where('key', $key)->find();
            if (!$config) {
                return false;
            }
            
            $result = Db::name('system_config')->where('key', $key)->delete();
            
            if ($result) {
                $this->clearConfigCache($key, $config['group']);
                return true;
            }
            
            return false;
            
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 初始化默认配置
     * @return bool
     */
    public function initDefaultConfigs(): bool
    {
        try {
            $sort = 0;
            foreach (self::DEFAULT_CONFIGS as $group => $configs) {
                foreach ($configs as $key => $config) {
                    $existing = Db::name('system_config')->where('key', $key)->find();
                    if (!$existing) {
                        $data = [
                            'key' => $key,
                            'value' => $this->formatValue($config['value'], $config['type']),
                            'desc' => $config['desc'],
                            'type' => $config['type'],
                            'group' => $group,
                            'options' => '',
                            'sort' => $sort++,
                            'status' => 1,
                            'create_time' => time(),
                            'update_time' => time()
                        ];
                        
                        Db::name('system_config')->insert($data);
                    }
                }
            }
            
            $this->clearAllConfigCache();
            return true;
            
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 验证配置值
     * @param string $key 配置键
     * @param mixed $value 配置值
     * @param string $type 配置类型
     * @return array
     */
    public function validateConfig(string $key, $value, string $type): array
    {
        $errors = [];
        
        switch ($type) {
            case 'number':
                if (!is_numeric($value)) {
                    $errors[] = '必须是数字';
                }
                break;
                
            case 'bool':
                if (!is_bool($value) && !in_array($value, [0, 1, '0', '1', 'true', 'false'])) {
                    $errors[] = '必须是布尔值';
                }
                break;
                
            case 'json':
                if (is_string($value)) {
                    json_decode($value);
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        $errors[] = '必须是有效的JSON格式';
                    }
                }
                break;
                
            case 'email':
                if ($value && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $errors[] = '必须是有效的邮箱地址';
                }
                break;
                
            case 'url':
                if ($value && !filter_var($value, FILTER_VALIDATE_URL)) {
                    $errors[] = '必须是有效的URL地址';
                }
                break;
        }
        
        // 自定义验证规则
        $customRules = $this->getCustomValidationRules();
        if (isset($customRules[$key])) {
            $rule = $customRules[$key];
            if (isset($rule['min']) && is_numeric($value) && $value < $rule['min']) {
                $errors[] = "值不能小于 {$rule['min']}";
            }
            if (isset($rule['max']) && is_numeric($value) && $value > $rule['max']) {
                $errors[] = "值不能大于 {$rule['max']}";
            }
            if (isset($rule['required']) && $rule['required'] && empty($value)) {
                $errors[] = '该配置项为必填项';
            }
        }
        
        return [
            'valid' => empty($errors),
            'errors' => $errors
        ];
    }

    /**
     * 获取配置分组
     * @return array
     */
    public function getConfigGroups(): array
    {
        return self::CONFIG_GROUPS;
    }

    /**
     * 获取配置类型
     * @return array
     */
    public function getConfigTypes(): array
    {
        return self::CONFIG_TYPES;
    }

    /**
     * 导出配置
     * @param string $group 配置分组
     * @return array
     */
    public function exportConfigs(string $group = ''): array
    {
        $configs = $this->getAllConfigs($group);
        $result = [];
        
        foreach ($configs as $groupKey => $groupData) {
            foreach ($groupData['configs'] as $key => $config) {
                $result[] = [
                    'key' => $key,
                    'value' => $config['raw_value'],
                    'desc' => $config['desc'],
                    'type' => $config['type'],
                    'group' => $groupKey,
                    'sort' => $config['sort']
                ];
            }
        }
        
        return $result;
    }

    /**
     * 导入配置
     * @param array $configs 配置数组
     * @return bool
     */
    public function importConfigs(array $configs): bool
    {
        try {
            Db::startTrans();
            
            foreach ($configs as $config) {
                $this->set(
                    $config['key'],
                    $config['value'],
                    $config['desc'] ?? '',
                    $config['type'] ?? 'text',
                    $config['group'] ?? 'basic'
                );
            }
            
            Db::commit();
            return true;
            
        } catch (\Exception $e) {
            Db::rollback();
            return false;
        }
    }

    /**
     * 解析配置值
     * @param string $value 原始值
     * @param string $type 类型
     * @return mixed
     */
    private function parseValue(string $value, string $type)
    {
        switch ($type) {
            case 'bool':
                return in_array($value, ['1', 'true', 'on'], true);
                
            case 'number':
                return is_numeric($value) ? ($value == (int)$value ? (int)$value : (float)$value) : 0;
                
            case 'json':
                $decoded = json_decode($value, true);
                return $decoded !== null ? $decoded : [];
                
            default:
                return $value;
        }
    }

    /**
     * 格式化配置值
     * @param mixed $value 配置值
     * @param string $type 类型
     * @return string
     */
    private function formatValue($value, string $type): string
    {
        switch ($type) {
            case 'bool':
                return $value ? '1' : '0';
                
            case 'json':
                return is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : (string)$value;
                
            default:
                return (string)$value;
        }
    }

    /**
     * 清除配置缓存
     * @param string $key 配置键
     * @param string $group 配置分组
     */
    private function clearConfigCache(string $key, string $group): void
    {
        Cache::delete('config_' . $key);
        Cache::delete('system_configs');
        Cache::delete('system_configs_' . $group);
    }

    /**
     * 清除所有配置缓存
     */
    private function clearAllConfigCache(): void
    {
        // 清除所有配置相关的缓存
        $groups = array_keys(self::CONFIG_GROUPS);
        foreach ($groups as $group) {
            Cache::delete('system_configs_' . $group);
        }
        Cache::delete('system_configs');
        
        // 清除单个配置缓存（这里可以扩展为更精确的缓存管理）
        foreach (self::DEFAULT_CONFIGS as $groupConfigs) {
            foreach ($groupConfigs as $key => $config) {
                Cache::delete('config_' . $key);
            }
        }
    }

    /**
     * 获取默认配置（按分组）
     * @param string $group 分组
     * @return array
     */
    private function getDefaultConfigsByGroup(string $group = ''): array
    {
        $result = [];
        $configs = $group ? [self::DEFAULT_CONFIGS[$group] ?? []] : self::DEFAULT_CONFIGS;
        
        foreach ($configs as $groupKey => $groupConfigs) {
            if ($group && $groupKey !== $group) continue;
            
            $result[$groupKey] = [
                'name' => self::CONFIG_GROUPS[$groupKey] ?? $groupKey,
                'configs' => []
            ];
            
            foreach ($groupConfigs as $key => $config) {
                $result[$groupKey]['configs'][$key] = [
                    'key' => $key,
                    'value' => $config['value'],
                    'raw_value' => $this->formatValue($config['value'], $config['type']),
                    'type' => $config['type'],
                    'desc' => $config['desc'],
                    'options' => null,
                    'sort' => 0,
                    'status' => 1
                ];
            }
        }
        
        return $result;
    }

    /**
     * 获取自定义验证规则
     * @return array
     */
    private function getCustomValidationRules(): array
    {
        return [
            'login_attempts' => ['min' => 1, 'max' => 20, 'required' => true],
            'session_timeout' => ['min' => 300, 'max' => 86400],
            'password_min_length' => ['min' => 4, 'max' => 32],
            'upload_max_size' => ['min' => 1, 'max' => 1024],
            'max_approval_steps' => ['min' => 1, 'max' => 20],
            'data_retention_days' => ['min' => 1, 'max' => 3650]
        ];
    }
}